/*
    Copyright (C) 2004  Brano Kemen

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include "coid/comm/commtypes.h"
#include "coid/comm/str.h"
#include "coid/comm/dir.h"

#include "coid/comm/binstream/stdstream.h"

using namespace coid;


typedef int (* fn_coid_server_start)( int& port, int (*cancel_cbk)(int) );
typedef int (* fn_coid_server_stop)();
typedef int (* fn_coid_get_version)( charstr & );


static const char * g_look_libserver[] = {".", "/usr/lib/coid", "/usr/local/lib/coid", 0};

static stdoutstream _stdout;
static binstream* Out = 0;

static fn_coid_server_stop coid_server_stop = 0;


////////////////////////////////////////////////////////////////////////////////
int cancel_request( int restart )
{
    if( restart )
    {
        //spawn another
    }

    return 0;
}

////////////////////////////////////////////////////////////////////////////////
int printerr( const charstr& lib, const char* err )
{
    const char* errs = "Error loading coid server library ";

    *Out << errs << lib;
	if(err)
        *Out << "\n  " << err;
    *Out << "\n";
    return 3;
}

////////////////////////////////////////////////////////////////////////////////
int coid_run( int& port, const char* libserver, const char* conf )
{
    Out = &_stdout;

    if( conf && directory::chdir(conf) != 0 ) {
        *Out << "Error changing working directory to " << conf << "\n";
        return 4;
    }


    sysDynamicLibrary server_lib;
    const char ** plib = g_look_libserver;
    charstr tmplib;

    if(libserver)
        tmplib = libserver;
    else {
        for( ; *plib!=0; ++plib ) {
            tmplib = *plib;
            tmplib += "/libcoidserver.so";
            if( directory::is_valid_file(tmplib) )
                break;
        }
    }

    server_lib.open( tmplib.ptr() );
    if( !server_lib.is_valid() ) {
        if(libserver)
            *Out << "Explicit path to coid server library not found: " << tmplib << BINSTREAM_FLUSH;
        else if( *plib == 0 ) {
            *Out << "No implicit path contains the coid server library libcoidserver.so\nLooked in: ";
            for( const char ** p = g_look_libserver; *p != 0; ++p ) {
                if( p != g_look_libserver )  *Out << ", ";
                *Out << *p;
            }
            *Out << BINSTREAM_FLUSH;
        }
        else
            *Out << "Implicit path to coid server library could not be opened: " << tmplib << BINSTREAM_FLUSH;
        return 2;
    }
    *Out << "Using coid server library from: " << tmplib << BINSTREAM_FLUSH;


	void* fnc0 = server_lib.getFuncAddress( "coid_get_version" );
	if(!fnc0)
        return printerr( tmplib, server_lib.error() );

	charstr ver;
	fn_coid_get_version coid_get_version = (fn_coid_get_version) fnc0;
	coid_get_version( ver );
    *Out << "Coid server version: " << ver << "\n";

    void* fnc1 = server_lib.getFuncAddress( "coid_server_start" );
    if(!fnc1)
        return printerr( tmplib, server_lib.error() );

    void* fnc2 = server_lib.getFuncAddress( "coid_server_stop" );
    if(!fnc2)
        return printerr( tmplib, server_lib.error() );



    fn_coid_server_start coid_server_start = (fn_coid_server_start) fnc1;
    coid_server_stop = (fn_coid_server_stop) fnc2;

    return coid_server_start( port, &cancel_request );
}

////////////////////////////////////////////////////////////////////////////////
void coid_stop()
{
    if( coid_server_stop )
        coid_server_stop();
}